/**
 * 不管使用什么方式来管理内存， 内存管理都会有以下的生命周期
 * 1. 分配申请你需要的内存
 * 2. 使用分配的内存
 * 3. 不再使用的时候， 对其进行释放
 */

// js中是自动分配内存
// 1. js对于基本数据类型的分配会在执行的时候直接在栈空间中进行分配
// 2. 对于引用类型的分配会在执行的时候直接在堆空间中开辟一块空间， 将这块空间的指针返回值变量引用



js的垃圾回收
烂机回收器： 算法
1. 引用计数
    - 每个对象都有一个引用计数器， 当有新的引用指向这个对象时， 计数器加1
    - 当引用被删除时， 计数器减1
    - 当计数器为0时， 说明没有引用指向这个对象， 这个对象就会被回收

    var obj = {
      name: 'zhangsan'
    }
    var info = {
      name: 'lisi',
      friend: obj
    }
    var per =  {
      name: 'wangwu',
      friend: obj
    }
    现在 retain count = 3

    引用计数有一个很大的弊端： 循环引用
    var obj1 = {
      friend: obj2
    }
    var obj2 = {
      friend: obj1
    }
    现在 obj1 和 obj2 的引用计数都为1， 但是这两个对象都无法被回收， 因为它们互相引用着对方
    解决循环引用的问题：
    - 通过弱引用来解决循环引用的问题
    - 弱引用： 不会增加对象的引用计数， 当对象没有其他引用时， 可以被回收
    - 在js中， 可以使用WeakMap和WeakSet来实现弱引用
    - WeakMap： 键名所引用的对象都是弱引用， 即垃圾回收机制不将该引用考虑在内
    - WeakSet： 成员只能是对象， 而不能是其他类型的值

2. 标记清除
    - 标记清除算法是通过标记所有可达的对象， 然后清除所有不可达的对象
    - 可达的对象是指从根对象（如全局对象、函数调用栈等）可以直接或间接访问到的对象
    - 标记清除算法的步骤：
      1. 从根对象开始， 遍历所有可达的对象， 标记它们为可达
      2. 遍历所有对象， 清除所有不可达的对象
      3. 重复以上步骤， 直到所有对象都被遍历一遍
      4. 内存回收完成